import type { RequestConfig } from './service/request_handler'
import type { RequestSchedulerQueue } from './service/request_scheduler'
import { logger } from '../../types/constants'
import { SYMBOLS } from '../../types/interfaces'
import { RequestType } from './service/request_handler'
import { RequestScheduler } from './service/request_scheduler'

/**
 * 请求场景枚举
 */
export enum RequestScenario {
  SINGLE = 'single', // 单个请求
  BATCH = 'batch', // 批量请求
  PRIORITY = 'priority', // 高优先级请求
  BACKGROUND = 'background', // 后台请求
}

/**
 * 执行器配置接口
 */
export interface ExecutorConfig {
  scenario?: RequestScenario
  // concurrent?: number // 并发数（暂未使用）
  priority?: number // 优先级（1-10，数字越大优先级越高）
}

/**
 * 请求执行结果
 */
export interface ExecutionResult<T = any> {
  success: boolean
  cached: boolean
  data?: T
  error?: any
  requestId?: number
  scenario: RequestScenario
  retryCount: number
  duration: number
}

/**
 * 批量执行结果
 */
export interface BatchExecutionResult<T = any> {
  total: number
  success: number
  failed: number
  successRate: number
  results: Map<string, ExecutionResult<T>>
  duration: number
}

/**
 * 请求执行器
 */
export class RequestExecutor {
  private readonly name: string = 'RequestExecutor'
  static instance: RequestExecutor
  private readonly scheduler = RequestScheduler.getInstance()

  static getInstance(): RequestExecutor {
    if (!RequestExecutor.instance) {
      RequestExecutor.instance = new RequestExecutor()
    }
    return RequestExecutor.instance
  }

  /**
   * 执行单个请求
   */
  async executeRequest<T = any>(
    url: string,
    config: ExecutorConfig & RequestConfig = {},
  ): Promise<ExecutionResult<T>> {
    const startTime = Date.now()
    const scenario = config.scenario || RequestScenario.SINGLE
    const requestConfig: RequestConfig = this.buildRequestConfig(config, scenario)

    const { retryCount = 0 } = requestConfig

    logger.debug(`[${this.name}] 开始执行单个请求`, {
      url,
      scenario,
      retryCount,
    })

    try {
      const response = await this.scheduler.scheduleRequest<T>(url, requestConfig)
      const { status, cached = false, data, error, requestId, retryCount: responseRetryCount, duration } = response

      if (['success', 'cached'].includes(status)) {
        logger.debug(`[${this.name}] ${SYMBOLS.STATUS.SUCCESS} 请求执行成功`, {
          url,
          cached,
          scenario,
          retryCount: responseRetryCount,
          duration: `${duration}ms`,
        })

        return {
          success: true,
          cached,
          data,
          requestId,
          scenario,
          retryCount: responseRetryCount,
          duration,
        }
      }
      else {
        // 请求失败但有缓存数据
        if (data) {
          logger.warn(`[${this.name}] ${SYMBOLS.STATUS.WARNING} 请求失败但使用缓存数据`, {
            url,
            error,
            scenario,
            duration: `${duration}ms`,
          })

          return {
            success: true,
            cached: true,
            data,
            requestId,
            scenario,
            retryCount: responseRetryCount,
            duration,
          }
        }

        throw new Error(error?.message || '请求失败')
      }
    }
    catch (error) {
      const duration = Date.now() - startTime

      logger.error(`[${this.name}] ${SYMBOLS.STATUS.ERROR} 请求执行失败`, {
        url,
        scenario,
        retryCount: 0,
        duration: `${duration}ms`,
      })

      throw error
    }
  }

  /**
   * 执行高优先级请求
   */
  async executeRequestWithPriority<T = any>(url: string, config: ExecutorConfig & RequestConfig = {}): Promise<ExecutionResult<T>> {
    return this.executeRequest<T>(url, {
      ...config,
      scenario: RequestScenario.PRIORITY,
    })
  }

  /**
   * 执行后台请求（低优先级）
   */
  async executeRequestWithBackground<T = any>(url: string, config: ExecutorConfig & RequestConfig = {}): Promise<ExecutionResult<T>> {
    return this.executeRequest<T>(url, {
      ...config,
      scenario: RequestScenario.BACKGROUND,
    })
  }

  /**
   * 构建请求配置
   */
  private buildRequestConfig(
    config: ExecutorConfig & RequestConfig,
    scenario: RequestScenario,
  ): RequestConfig & ExecutorConfig {
    const baseConfig: RequestConfig & ExecutorConfig = {
      useGM: config.useGM ?? true,
      requestType: RequestType.JSON,
      priority: 1,
      retryCount: config.retryCount || 0,
    }

    // 根据场景调整配置
    switch (scenario) {
      case RequestScenario.PRIORITY:
        return {
          ...baseConfig,
          priority: config.priority || 8, // 高优先级
          timeout: config.timeout || 5000,
          retryCount: config.retryCount || 1, // 较少重试
          minInterval: 0, // 高优先级不限制间隔
        }

      case RequestScenario.BACKGROUND:
        return {
          ...baseConfig,
          priority: config.priority || 2, // 低优先级
          timeout: config.timeout || 30000, // 较长超时
          retryCount: config.retryCount || 0, // 不重试
          minInterval: config.minInterval || 2000, // 后台请求增加间隔
        }

      case RequestScenario.BATCH:
        return {
          ...baseConfig,
          timeout: config.timeout || 10000,
          minInterval: config.minInterval || 1000,
        }

      case RequestScenario.SINGLE:
      default:
        return {
          ...baseConfig,
          timeout: config.timeout || 8000,
          minInterval: config.minInterval || 500,
        }
    }
  }

  /**
   * 获取执行器状态
   */
  getExecutorStatus(): {
    scheduler: RequestSchedulerQueue
    timestamp: number
  } {
    const schedulerStatus = this.scheduler.getQueueStatus()
    return {
      scheduler: schedulerStatus,
      timestamp: Date.now(),
    }
  }

  /**
   * 清空所有队列
   */
  clearAllQueues(): void {
    this.scheduler.clearQueue()
    logger.info(`[${this.name}] ${SYMBOLS.OTHERS.CLEAR} 清空所有执行队列`)
  }
}
